package com.wsseieiei.fireballgame.entity;

import com.wsseieiei.fireballgame.init.EffectInit;
import net.minecraft.core.particles.ParticleTypes;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.network.chat.Component;
import net.minecraft.network.syncher.EntityDataAccessor;
import net.minecraft.network.syncher.EntityDataSerializers;
import net.minecraft.network.syncher.SynchedEntityData;
import net.minecraft.server.level.ServerBossEvent;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.sounds.SoundEvent;
import net.minecraft.sounds.SoundEvents;
import net.minecraft.world.BossEvent;
import net.minecraft.world.effect.MobEffectInstance;
import net.minecraft.world.effect.MobEffects;
import net.minecraft.world.entity.*;
import net.minecraft.world.entity.ai.attributes.AttributeSupplier;
import net.minecraft.world.entity.ai.attributes.Attributes;
import net.minecraft.world.entity.ai.goal.LookAtPlayerGoal;
import net.minecraft.world.entity.ai.goal.RandomLookAroundGoal;
import net.minecraft.world.entity.ai.goal.WaterAvoidingRandomStrollGoal;
import net.minecraft.world.entity.ai.goal.target.HurtByTargetGoal;
import net.minecraft.world.entity.ai.goal.target.NearestAttackableTargetGoal;
import net.minecraft.world.entity.animal.IronGolem;
import net.minecraft.world.entity.monster.Blaze;
import net.minecraft.world.entity.monster.Monster;
import net.minecraft.world.entity.monster.Zombie;
import net.minecraft.world.entity.monster.ZombifiedPiglin;
import net.minecraft.world.entity.npc.AbstractVillager;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.level.Explosion;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.pathfinder.BlockPathTypes;
import net.minecraft.world.phys.AABB;
import org.jetbrains.annotations.NotNull;

import javax.annotation.Nullable;
import java.util.List;
import java.util.Random;
import java.util.function.Predicate;

import static net.minecraft.world.BossEvent.BossBarColor.RED;

//继承自烈焰人
public class EntitySb extends Blaze {
    //boss血条信息
    private final ServerBossEvent bossInfo = (ServerBossEvent)(new ServerBossEvent(this.getDisplayName(), BossEvent.BossBarColor.PURPLE, BossEvent.BossBarOverlay.PROGRESS)).setDarkenScreen(true);
    private static final EntityDataAccessor<Integer> DATA_ID_INV = SynchedEntityData.defineId(EntitySb.class, EntityDataSerializers.INT);
    //设置boss类型为不死亡灵类的生物
    private final Predicate<LivingEntity> LIVING_ENTITY_SELECTOR = (p_31504_) -> p_31504_.getMobType() != MobType.UNDEAD && p_31504_.attackable() && p_31504_.getType()==this.getType();



    public EntitySb(EntityType<? extends Blaze> type, Level worldIn) {
        super(type, worldIn);
        this.xpReward = 15000;
        this.isNonBoss();
        this.isSunSensitive();
        this.setPathfindingMalus(BlockPathTypes.LAVA, 8.0F);
    }

    //是否怕阳光
    protected boolean isSunSensitive() {
        return false;
    }

    public void aiStep() {
        if (!this.onGround && this.getDeltaMovement().y < 0.0D) {
            this.setDeltaMovement(this.getDeltaMovement().multiply(1.0D, 0.6D, 1.0D));
        }

        if (this.level.isClientSide) {
            if (this.random.nextInt(24) == 0 && !this.isSilent()) {
                this.level.playLocalSound(this.getX() + 0.5D, this.getY() + 0.5D, this.getZ() + 0.5D, SoundEvents.DRAGON_FIREBALL_EXPLODE, this.getSoundSource(), 1.0F + this.random.nextFloat(), this.random.nextFloat() * 0.7F + 0.3F, false);
            }

            for(int i = 0; i < 2; ++i) {
                this.level.addParticle(ParticleTypes.ASH, this.getRandomX(0.5D), this.getRandomY(), this.getRandomZ(0.5D), 0.0D, 0.0D, 0.0D);
            }

        }

        super.aiStep();
    }

    //设置生物属性(最大血量、移动速度、攻击力、护甲值等)
    public static AttributeSupplier.Builder prepareAttributes() {
        return Monster.createMonsterAttributes().add(Attributes.MAX_HEALTH, 1200.0D).
                add(Attributes.MOVEMENT_SPEED, 0.28D).
                add(Attributes.FOLLOW_RANGE, 48.0D).
                add(Attributes.ARMOR, 3.0D).
                add(Attributes.ARMOR_TOUGHNESS, 10.0D).
                add(Attributes.KNOCKBACK_RESISTANCE, 10.0D).
                add(Attributes.ATTACK_DAMAGE, 30.0D);

    }

    //给生物设置攻击行为
    @Override
    protected void registerGoals() {
        super.registerGoals();
        this.goalSelector.addGoal(1, new RandomLookAroundGoal(this));
        this.goalSelector.addGoal(2, new LookAtPlayerGoal(this, Player.class, 8.0F));
        this.targetSelector.addGoal(1, new NearestAttackableTargetGoal<>(this, LivingEntity.class, 0, false, false, LIVING_ENTITY_SELECTOR));
        this.addBehaviourGoals();
    }

    //给生物添加其行为
    protected void addBehaviourGoals() {
        this.goalSelector.addGoal(7, new WaterAvoidingRandomStrollGoal(this, 1.0D));
        this.targetSelector.addGoal(1, (new HurtByTargetGoal(this)).setAlertOthers(ZombifiedPiglin.class));
        this.targetSelector.addGoal(2, new NearestAttackableTargetGoal<>(this, Player.class, true));
        this.targetSelector.addGoal(3, new NearestAttackableTargetGoal<>(this, AbstractVillager.class, false));
        this.targetSelector.addGoal(3, new NearestAttackableTargetGoal<>(this, IronGolem.class, true));

    }


    //生物攻击其他生物
    public boolean doHurtTarget(@NotNull Entity entityIn) {
        if(!super.doHurtTarget(entityIn))
        {
            return false;
        }
        else{
            //如果攻击的对象是生物，就给这个对象一个凋零效果和失明效果和缓慢和缓慢效果，持续60ticks(20ticks=1s)
            //如果攻击的对象是生物，就给这个对象一个32秒的着火
            if(entityIn instanceof LivingEntity)
            {
                ((LivingEntity)entityIn).addEffect(new MobEffectInstance(MobEffects.WITHER, 60,3,true,true));
                ((LivingEntity)entityIn).addEffect(new MobEffectInstance(MobEffects.BLINDNESS, 60,3,true,true));
                ((LivingEntity)entityIn).addEffect(new MobEffectInstance(MobEffects.MOVEMENT_SLOWDOWN, 60,3,true,true));
                ((LivingEntity)entityIn).addEffect(new MobEffectInstance(EffectInit.BURN.get(), 200,3,true,true));
                entityIn.setSecondsOnFire(32);
            }
            return true;
        }
    }

    //生物死亡音效
    @Override
    protected SoundEvent getDeathSound() {
        return SoundEvents.WITHER_DEATH;
    }

    // 生物在玩家身边的音效
    protected SoundEvent getAmbientSound() {
        return SoundEvents.ENDER_DRAGON_AMBIENT;
    }

    protected float getStandingEyeHeight(@NotNull Pose p_213348_1_, @NotNull EntityDimensions p_213348_2_) {
        return 1F;
    }

    public void setInvulnerableTicks(int p_82215_1_) {
        this.entityData.define(DATA_ID_INV, p_82215_1_);
    }

    public void readAdditionalSaveData(@NotNull CompoundTag p_70037_1_) {
        super.readAdditionalSaveData(p_70037_1_);
        this.setInvulnerableTicks(p_70037_1_.getInt("Invul"));
        if (this.hasCustomName()) {
            this.bossInfo.setName(this.getDisplayName());
        }
    }

    public void setCustomName(@Nullable Component p_200203_1_) {
        super.setCustomName(p_200203_1_);
        this.bossInfo.setName(this.getDisplayName());
    }



    protected void customServerAiStep() {
        super.customServerAiStep();
        if(this.isSunSensitive()){
            this.addEffect(new MobEffectInstance(MobEffects.FIRE_RESISTANCE, 20*10,1,true,true));
        }

        Random ran = new Random();
        if(this.getHealth() >= 20.0F && this.getHealth()<=30.0F)
        {
            for(int i=0;i<5;i++)
                this.heal(ran.nextFloat());
        }

        if(this.getHealth() >= 60.0F && this.getHealth()<=65.0F)
        {
            for(int i=0;i<4;i++)
                this.heal(1.5F*ran.nextFloat());
        }

        if((this.getHealth() >= 100.0F && this.getHealth()<=300.0F)||(this.getHealth() >= 700.0F && this.getHealth()<=900.0F))
        {
            Explosion.BlockInteraction explosion$blockinteraction = net.minecraftforge.event.ForgeEventFactory.getMobGriefingEvent(this.level, this) ? Explosion.BlockInteraction.DESTROY : Explosion.BlockInteraction.NONE;
            this.level.explode(this, this.getX(), this.getY(), this.getZ(), (float)4 * 2.0F, explosion$blockinteraction);
            try{
                for(int i=0;i<10;++i){
                    Zombie smallBoss = new Zombie(EntityType.ZOMBIE, this.level);
                    smallBoss.setPos(this.getX(),this.getY(),this.getZ());
                    smallBoss.setHealth(60);
                    smallBoss.addEffect(new MobEffectInstance(MobEffects.FIRE_RESISTANCE, 2147483647,1,true,true));
                    this.level.addFreshEntity(smallBoss);
                }
                this.setHealth(this.getHealth()-200.0F);
            } catch (Exception ignored) {
                this.setHealth(this.getHealth()+200.0F);
            }
        }

        if(this.getHealth() >= 20.0F && this.getHealth()<=30.0F)
        {
            Explosion.BlockInteraction explosion$blockinteraction = net.minecraftforge.event.ForgeEventFactory.getMobGriefingEvent(this.level, this) ? Explosion.BlockInteraction.DESTROY : Explosion.BlockInteraction.NONE;
            this.level.explode(this, this.getX(), this.getY(), this.getZ(), (float)4 * 2.0F, explosion$blockinteraction);
            this.kill();
        }

        try{
            List<Entity> needAttackEntitys = this.level.getEntities(this, new AABB(this.getX() - 5.0D, this.getY() -10.0D, this.getZ() - 5.0D, this.getX() + 5.0D, this.getY() + 10.0D, this.getZ() + 5.0D), Entity::isAlive);
            for (Entity entityIn : needAttackEntitys) {
                if (!(entityIn.getType()==this.getType())){
                    ((LivingEntity)entityIn).addEffect(new MobEffectInstance(MobEffects.BLINDNESS, 60,255,true,true));
                    ((LivingEntity)entityIn).addEffect(new MobEffectInstance(MobEffects.MOVEMENT_SLOWDOWN, 60,5,true,true));
                    ((LivingEntity)entityIn).addEffect(new MobEffectInstance(MobEffects.NIGHT_VISION, 60,1,true,true));
                    ((LivingEntity)entityIn).addEffect(new MobEffectInstance(EffectInit.BURN.get(), 60,3,true,true));
                }
            }
        } catch (Exception ignored) {
        }


        this.bossInfo.setProgress(this.getHealth() / this.getMaxHealth());
    }

    public void isNonBoss(){}

    //什么时候能看见boss血条
    public void startSeenByPlayer(@NotNull ServerPlayer p_184178_1_) {
        super.startSeenByPlayer(p_184178_1_);
        this.bossInfo.addPlayer(p_184178_1_);
        this.bossInfo.setColor(RED);
    }

    //什么时候看不见boss血条
    public void stopSeenByPlayer(@NotNull ServerPlayer p_184203_1_) {
        super.stopSeenByPlayer(p_184203_1_);
        this.bossInfo.removePlayer(p_184203_1_);
    }
}